package com.test.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class EchoServer {

	public final static int SERVER_PORT = 11891;
	ServerSocket socketServer;

	public EchoServer() {
		try {
			// Create the server socket.
			socketServer = new ServerSocket(SERVER_PORT);
		} catch (IOException ioe) {
			System.out.printf("\nCould not create server socket at %d. Quitting.\n", SERVER_PORT);
			System.exit(-1);
		}

		System.out.printf("\nListening for clients on %d...\n", SERVER_PORT);

		// Successfully created Server Socket. Now wait for connections.
		int id = 0;
		while (true) {
			try {
				// Accept incoming connections.
				Socket clientSocket = socketServer.accept();

				clientSocket.setSoTimeout(5 * 1000);

				// accept() will block until a client connects to the server.
				// If execution reaches this point, then it means that a client
				// socket has been accepted.

				// For each client, we will start a service thread to
				// service the client requests. This is to demonstrate a
				// multithreaded server, although not required for such a
				// trivial application. Starting a thread also lets our
				// EchoServer accept multiple connections simultaneously.

				// Start a service thread

				Handler handler = new Handler(clientSocket, id++);
				handler.start();
				Thread.sleep(1000 * 10);
				handler.send("xxxxxxxxxxxxxxx");
			} catch (Exception ex) {
				System.out.println("Exception encountered on accept. Ignoring. Stack Trace :");
				ex.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		new EchoServer();
	}

	class Handler extends Thread {
		private Socket socketConn;
		private int connId = -1;
		private BufferedReader in = null;
		private PrintWriter out = null;

		Handler(Socket s, int connId) {
			this.socketConn = s;
			this.connId = connId;
		}

		public void run() {

			// Print out details of this connection
			System.out.printf("Accepted Client[ID=%s, Address=%s].\n", connId, socketConn.getInetAddress().getHostAddress());

			try {
				in = new BufferedReader(new InputStreamReader(socketConn.getInputStream()));
				out = new PrintWriter(new OutputStreamWriter(socketConn.getOutputStream()));

				// At this point, we can read for input and reply with
				// appropriate output.

				// Run in a loop until m_bRunThread is set to false
				while (true) {
					// read incoming stream
					String clientCommand = in.readLine();

					if (clientCommand != null) {
						System.out.printf("Client[%s] Says: %s\n", connId, clientCommand);
					}

				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				close();
			}
		}

		public void send(String msg) {
			out.println(msg);
			out.flush();
		}

		public void close() {
			try {
				in.close();
				out.close();
				socketConn.close();
				System.out.printf("Client[%s] is closed.\n", connId);
			} catch (IOException ioe) {
				ioe.printStackTrace();
			}
		}
	}
}
